id: 4318993525 | 楼主:lyh娘 | 返回首页
id: 82894125306
1L | 作者:lyh娘 | 发布于 2016-01-23 22:05
这东西我早就做出来了,原理很简单,觉得自己藏着掖着不太好,遂发帖造福(个蛋啊)大众
现在大家使用的存档都是INI格式,几乎无一例外
那么我们这次就对INI存档做一个小修改,给它加一个签名,读档之前先验证这个签名是否符合,不符合的话直接清档
这个签名我们使用不可逆的算法进行生成,我会给出绝大部分的源码,但是具体的签名算法需要大家在我给出的指引下自己写,这样除了有mfa源文件的人以外,谁都别想手动修改你的存档了!
图中是我给某个万年巨坑制作的存档格式
id: 82894141571
2L | 作者:lyh娘 | 发布于 2016-01-23 22:05
等我从厕所出去接着写
id: 82894775593
3L | 作者:lyh娘 | 发布于 2016-01-23 22:16
注意:本文假设读者有一定的代码水平,若你完全没接触过MMF的代码,可能看着会很吃力,或者照做做不出来
大体思路:
读档前检测签名是否正确,若不正确,清档
存档后打上新的签名
为了防止读档后存档前存档被修改,读档时把整个存档文件读进内存,存档前恢复。
下面我们将以最新完整版RainbowEngine为例,讲解带签名存档的制作方法
工欲善其事必先利其器,开始前,请各位到Extension manager中下载以下的扩展:
id: 82894828673
4L | 作者:lyh娘 | 发布于 2016-01-23 22:17
不小心碰到Ctrl+回车了
工欲善其事必先利其器,开始前,请各位到Extension manager中下载以下的扩展:
String Parser
CRC32 Object
id: 82895056469
5L | 作者:lyh娘 | 发布于 2016-01-23 22:21
分析RainbowEngine的存档读档情况:
标题画面读取设置,两个设置画面保存设置
选择存档画面读取存档(读),可以删除存档(写)
大地图画面可以保存游戏(写)
标题画面的设置明显会对我们的工作起到干扰,因为如果连它们一起签名,最后的代码会麻烦很多。
所以我们直接改掉设置保存的文件名:分别在Start Start2 Start3中找到 INI: set current file to "./mafosav.ini"
把mafosav.ini改成别的文件名,使设置不干扰存档。
id: 82895328366
6L | 作者:lyh娘 | 发布于 2016-01-23 22:25
我们在选关画面和所有的大地图场景摆放一个String Parser和一个CRC32 Object,以便我们的代码进行使用。
同时取一个全局字符串(下文使用Global String A,请自行替换成自己要用的全局字符串)来保存读档时的存档内容,以防止在执行存档操作前有人修改存档,导致修改过的部分一起被签上正确的签名。
我们打开“选关画面”场景,在Event Editor中筛选INI Object,会看到如图所示的代码,这是我们要修改的部分。
id: 82896144466
7L | 作者:lyh娘 | 发布于 2016-01-23 22:39
补充说明:选关画面需要再摆放一个File Object,大地图画面不用
下文中调用到的所有Loop我们会在最后编写进全局事件。
我们在楼上所示图片的“Start of Frame”一行上增加代码:
Start loop "检测签名" 1 times
在28~30行(按照楼上的图自行对比,大家的可能不是这个行号)分别进行修改:
Start loop "恢复存档" 1 times
(这行的原有代码)
Start loop "执行签名" 1 times
修改后的代码应该是这样的(我只截了一行,注意三行都要修改)
打开需要存档的大地图场景(每个都要改)
在“保存游戏”事件组里同样如下修改仅有的一行:
Start loop "恢复存档" 1 times
(这行的原有代码)
Start loop "执行签名" 1 times
id: 82898400936
10L | 作者:lyh娘 | 发布于 2016-01-23 23:18
我的代码果然出问题了,重发
现在我们打开全局事件,开始编写新的代码:
以下代码请直接照搬:
On loop "检测签名"
- Set Global String A to GroupItemString$( "Ini", "checksum", "checksum" )
- INI: Set string "0" to item "checksum" in group "checksum" (右键选择:Set string (group - item))
- String Parser: Load from file "./mafosav.ini"
- Start loop "计算签名" 1 times
(注释:此处第二行的"0"可以替换成任意字符串,加密效果更好,只要注意后文"执行签名"出现的"0"也替换成你用的字符串就行了)
On loop "检测签名"
Global String A <> string$( "String Parser" )
- File: Delete file "./mafosav.ini"
- Set Global String A to ""
On loop "检测签名"
Global String A = string$( "String Parser" )
- INI: Set string Global String A to item "checksum" in group "checksum"
- String Parser: Load from file "./mafosav.ini"
- Set Global String A to string$( "String Parser")
On loop "恢复存档"
Global String A <> ""
- String Parser: Set source string to Global String A
- String Parser: Save to file "./mafosav.ini
On loop "执行签名"
- INI: Set string "0" to item "checksum" in group "checksum"
- String Parser: Load from file "./mafosav.ini"
- Start loop "计算签名" 1 times
- INI: Set string string$( "String Parser" ) to item "checksum" in group "checksum
- String Parser: Load from file "./mafosav.ini"
- Set Global String A to string$( "String Parser")
大家可以看到又引入了一个“计算签名”,这就是我们防修改存档的核心了,楼下讲解怎么计算
id: 82898953418
11L | 作者:lyh娘 | 发布于 2016-01-23 23:28
下面就是最重要的计算签名了
在全局事件中插入一行:On loop "计算签名"
这行代码要做的事:对String Parser里的文本进行不可逆、且他人无法推测的处理,使其变成一个签名。
这个处理应该具有确定性,就是说同一个输入文本必须确定地对应着同一个签名(就是说你不能引入随机数、变量一类的进去)
这个时候我前面说了却一直没用到的CRC32 Object就派上用场了:
下面我举一个最简单的例子(大家千万不要用这个):
On loop "计算签名"
- String Parser: Set source string to CRC32$( "CRC32 object", string$( "String Parser" ) )
这样就完成了一个最最最简单的签名。
这里正确的做法是对String Parser里的文本进行一些只有制作者自己知道的处理(比如在上面连接一些字)然后再取CRC32
当然取了CRC32之后可以再重复,再对结果进行一些别的处理再取CRC32……(1楼那个就是这么来的)
只要记住这个循环的输入和输出都在String Parser里就好了
下面举一段我目前正在实际使用的代码作为例子(不要吐槽天火同人):
(发完这贴之后永远的吧主吧友会改掉签名算法,不用我举这个例子了,你们不要费心写选关器了)
id: 82899122325
12L | 作者:lyh娘 | 发布于 2016-01-23 23:31
以上就完成了一个简单但完善的防修改存档格式的制作
没错,代码量就这么点,虽然可能有点难懂,但照着写就对了
今后各位可以不用怕选关器了,只要自己对“计算签名”的算法严格保密,谁都别想修改存档
id: 82900768780
13L | 作者:gurcd | 发布于 2016-01-24 00:02
沙发。没有打算加密存档,因为frame实在太多了,哪个地方忘记了都会出现小bug
id: 82901711155
14L | 作者:OnceBeta | 发布于 2016-01-24 00:21
打算直接用注册表存档⊙_⊙
File Object